home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 51 / Amiga Format CD51 (2000-03-10)(Future Publishing)(GB)[!][issue 2000-04].iso / -in_the_mag- / banging_the_metal / qdos / qdos4amiga2 / romsrc / ser / ser_asm
Text File  |  2000-01-03  |  19KB  |  892 lines

  1.     SECTION    SER
  2.  
  3.     INCLUDE    '/INC/QDOS_inc'
  4.     INCLUDE    '/INC/AMIGA_inc'
  5.     INCLUDE    '/INC/AMIGQDOS_inc'
  6.  
  7. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  8. ; SER1_asm - serial device driver
  9. ;      - last modified 03/11/97
  10.  
  11. ; These are all the necessary serial port related sources,
  12. ; required to implement a QDOS serial device on the Amiga
  13. ; computer.
  14.  
  15. ; Amiga-QDOS sources by Rainer Kowallik
  16. ;  ...latest changes by Mark J Swift
  17.  
  18. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  19. ;  Define some constants.
  20.  
  21. B_4800    EQU    745
  22. B_9600    EQU    372
  23.  
  24. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  25. ;  Define some extra serial variables
  26.  
  27. SER_EOF    EQU    SER_END        ; EOF (CLOSE) protocol
  28. SER_TXD    EQU    SER_EOF+2    ; last transmitted character
  29. SER_RXD    EQU    SER_TXD+2    ; last received character
  30. SER_MORE EQU    SER_RXD+2-SER_EOF ; length of extra ser vars
  31.  
  32. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  33. ;  ROM header
  34.  
  35. BASE:
  36.     dc.l    $4AFB0001    ; ROM recognition code
  37.     dc.w    0
  38.     dc.w    ROM_START-BASE
  39.     dc.b    0,36,'Amiga-QDOS SER device driver v1.09 ',$A
  40.  
  41. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  42. ;  start of ROM code
  43.  
  44. ROM_START:
  45.     movem.l    d0-d2/a0-a3,-(a7)
  46.  
  47. ; --------------------------------------------------------------
  48. ;  allocate memory for variables
  49.  
  50.     move.l    #SV_LEN,d1
  51.     moveq    #MT.ALCHP,d0
  52.     moveq    #0,d2
  53.     trap    #1
  54.  
  55.     tst.l    d0
  56.     bne    ROM_EXIT
  57.  
  58. ; --------------------------------------------------------------
  59. ;  address of SER variables
  60.  
  61.     move.l    a0,AV.SERV
  62.     move.l    a0,a3        ; address of linkage block
  63.  
  64. ; --------------------------------------------------------------
  65. ;  enter supervisor mode and disable interrupts
  66.  
  67.     trap    #0
  68.  
  69.     ori.w    #$0700,sr    ; disable interrupts
  70.  
  71. ; --------------------------------------------------------------
  72. ;  link a custom routine into level 7 interrupt server
  73.  
  74.     lea    AV.LVL7link,a1
  75.     lea    SV.LVL7link(a3),a2
  76.  
  77.     move.l    (a1),(a2)
  78.     move.l    a2,(a1)
  79.  
  80.     lea    MY_LVL7(pc),a1
  81.     move.l    a1,$04(a2)
  82.  
  83. ; --------------------------------------------------------------
  84. ;  link a custom routine into Trap #1 exception
  85.  
  86.     lea    AV.TRP1link,a1
  87.     lea    SV.TRP1link(a3),a2
  88.  
  89.     move.l    (a1),(a2)
  90.     move.l    a2,(a1)
  91.  
  92.     lea    MY_TRP1(pc),a1
  93.     move.l    a1,$04(a2)
  94.  
  95. ; --------------------------------------------------------------
  96. ;  routines necessary for device driver
  97.  
  98.     lea    SER_IO(pc),a2    ; Input/Output routine
  99.     move.l    a2,SV_AIO(a3)
  100.  
  101.     lea    SER_OPEN(pc),a2    ; OPEN routine
  102.     move.l    a2,SV_AOPEN(a3)
  103.  
  104.     lea    SER_CLOSe(pc),a2    ; CLOSE routine
  105.     move.l    a2,SV_ACLOS(a3)
  106.  
  107. ; --------------------------------------------------------------
  108. ;  routines necessary for IO.SERIO. (used by SER I/O routine)
  109.  
  110.     lea    SER_TST(pc),a2    ; test for pending input
  111.     move.l    a2,SV.PEND(a3)
  112.  
  113.     lea    SER_FBYT(pc),a2    ; fetch byte
  114.     move.l    a2,SV.FBYTE(a3)
  115.  
  116.     lea    SER_SBYT(pc),a2    ; send byte
  117.     move.l    a2,SV.SBYTE(a3)
  118.  
  119.     move.w    #$4E75,SV.RTS(A3) ; RTS instruction at $34
  120.  
  121. ; --------------------------------------------------------------
  122. ;  set up hardware
  123.  
  124.     bsr.s    INIT_HW
  125.  
  126. ; --------------------------------------------------------------
  127. ;  link in device driver
  128.  
  129.     lea    SV_LIO(a3),a0    ; link address
  130.     moveq    #MT.LIOD,d0    ; link in IO device driver
  131.     trap    #1
  132.  
  133. ; -------------------------------------------------------------
  134. ; link in external interrupt to act on port free
  135.  
  136.     lea    XINT_SERv(pc),a2    ; address of routine
  137.     move.l    a2,SV_AXINT(a3)
  138.     lea    SV_LXINT(a3),a0
  139.     moveq    #MT.LXINT,d0
  140.     trap    #1
  141.  
  142. ; -------------------------------------------------------------
  143. ; link in poll interrupt to re-enable serial send / receive
  144.  
  145.     lea    POLL_SERv(pc),a2    ; address of routine
  146.     move.l    a2,SV_APOLL(a3)
  147.     lea    SV_LPOLL(a3),a0
  148.     moveq    #MT.LPOLL,d0
  149.     trap    #1
  150.  
  151. ; --------------------------------------------------------------
  152. ;  enable interrupts and re-enter user mode
  153.  
  154.     andi.w    #$D8FF,sr
  155.  
  156. ; --------------------------------------------------------------
  157. ROM_EXIT:
  158.     movem.l    (a7)+,d0-d2/a0-a3
  159.  
  160.     rts
  161.  
  162. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  163. ;  set up hardware
  164.  
  165. INIT_HW:
  166.     move.l    d7,-(a7)
  167.  
  168.     move.b    CIAB_DDRA,d7
  169.     andi.b    #%00000111,d7
  170.     ori.b    #%11000000,d7    ; DTR(7),RTS(6) as outputs &
  171.     move.b    d7,CIAB_DDRA    ; CD(5),CTS(4),DSR(3) inputs
  172.  
  173.     MOVE.B    #%11000000,CIAB_PRA ; DTR(7) low (1) not ready to receive
  174.                   ; RTS(6) low (1) nothing to send
  175.  
  176.     MOVE.W    #B_9600,D0
  177.     BSET    #15,D0        ; 9 bit receive data
  178.     MOVE.W    D0,SERPER    ; Set baudrate
  179.  
  180.     move.w    #%0000100000000001,INTREQ ; clear interrupts
  181.     move.w    #%1000100000000001,INTENA ; enable RBF & TBE
  182.                         ; interrupts
  183.     move.l    (a7)+,d7
  184.     rts
  185.  
  186. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  187. ;  Serial open routine
  188.  
  189. SER_OPEN:
  190.     suba.w    #10,a7        ; room for 5 words on
  191.     MOVEA.L    A7,A3        ; stack.
  192.  
  193.     move.w    IO.NAME,a4    ; decode device name
  194.     jsr    (a4)
  195.  
  196.     BRA.S    SER_O_X        ; error
  197.     BRA.S    SER_O_X        ; error
  198.     BRA.S    SER_O_CHK    ; OK, check values
  199.  
  200.     DC.B    0,3,'SER',0
  201.     dc.w    5        ; 5 parameters
  202.  
  203.     dc.w    -1        ; word, no seperator
  204.     dc.w    1        ; default port
  205.  
  206.     dc.w    4        ; char value, 4 options
  207.     DC.B    'OEMS'        ; Parity
  208.  
  209.     DC.W    2        ; char value, 2 options
  210.     DC.B    'IH'        ; handshake
  211.  
  212.     dc.w    4        ; char value, 4 options
  213.     dc.b    'RNCL'        ; eol protocol
  214.  
  215.     dc.w    2        ; char value, 2 options
  216.     dc.b    'FZ'        ; eof protocol
  217.  
  218. ; --------------------------------------------------------------
  219. SER_O_NF:
  220.     moveq    #ERR.NF,d0    ; not found
  221.     bra    SER_O_X
  222.  
  223. ; --------------------------------------------------------------
  224. SER_O_IU:
  225.     moveq    #ERR.IU,d0    ; in use
  226.  
  227. ; --------------------------------------------------------------
  228. SER_O_X:
  229.     adda.w    #10,a7
  230.     ANDI.W    #$F8FF,SR
  231.     RTS
  232.  
  233. ; --------------------------------------------------------------
  234. SER_O_CHK:
  235.     ORI.W    #$0700,SR    ; disable interrupts
  236.  
  237.     MOVE.W    (A7),D4        ; get port
  238.     ble.s    SER_O_NF     ; <=0, bad value
  239.  
  240.     SUBQ.W    #2,D4
  241.     bgt.s    SER_O_NF     ; >2, bad value
  242.  
  243.     lea    SV_SER1C(a6),a5    ; Receive queue, channel 1
  244.     move.l    (a5),d0        ; address set?
  245.     BEQ.S    L00B56        ; no queue, no chan def blk
  246.  
  247.     movea.l    d0,a0
  248.     suba.w    #SER_RXQ,a0    ; addrs of old chan def blk
  249.     bclr    #7,SER_TXQ(a0)    ; output queue empty?
  250.     BNE.S    L00B6A        ; yes, so continue
  251.     bra.s    SER_O_IU     ; no, so exit with error
  252.  
  253. L00B56:
  254.     move.w    #(SER_END+SER_MORE),d1 ; allocate chan def block
  255.     move.w    MM.ALCHP,a4    ; for first time
  256.     JSR    (A4)
  257.     bne.s    SER_O_X        ; exit if error occured
  258.  
  259.     moveq    #SER_TXQL,d1    ; length of transmit queue
  260.     lea    SER_TXQ(a0),a2    ; address of transmit queue
  261.     move.w    IO.QSET,a4    ; set up queue (not used
  262.     jsr    (a4)        ; before
  263.  
  264. L00B6A:
  265.     moveq    #SER_RXQL,d1    ; length of receive queue
  266.     lea    SER_RXQ(a0),a2    ; address of receive queue
  267.     move.w    IO.QSET,a4    ; set up queue
  268.     jsr    (a4)
  269.  
  270.     move.l    a2,SV_SER1C(a6)    ; Receive queue, channel 1
  271.  
  272.     move.l    (a7),SER_CHNO(a0) ; store port number, parity
  273.     move.l    4(a7),SER_TXHS(a0) ; store handshake, protocol
  274.     move.w    8(a7),SER_EOF(a0) ; store EOF protocol
  275.  
  276.     subq.w    #1,SER_TXHS(a0)    ; <=0 ignore, 1 handshake
  277.     subq.w    #2,SER_PROT(a0)    ; <0 raw : 0 CR/LF : 1 CR : 2 LF
  278.     subq.w    #1,SER_EOF(a0)    ; <0 none : 0 FF : CTRL-Z
  279.  
  280. ; --------------------------------------------------------------
  281. ;  set up hardware
  282.  
  283.     move.b    #%01000000,CIAB_PRA ; DTR(7) high (0) ready to receive
  284.                   ; RTS(6) low (1) nothing to send
  285.  
  286. ; --------------------------------------------------------------
  287. SER_O_OK:
  288.     moveq    #ERR.OK,d0    ; signal "no error"
  289.     bra    SER_O_X
  290.  
  291. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  292. ;  serial close routine
  293.  
  294. SER_CLOSe:
  295.     tst.b    1+SER_EOF(a0)
  296.     blt.s    SER_C2        ; cont if no eof protocol
  297.  
  298.     beq.s    SER_C1        ; branch if FF protocol
  299.  
  300.     move.w    #26,d1        ; else send CTRL-Z
  301.     bra.s    SER_CLUP
  302.  
  303. SER_C1:
  304.     move.w    #12,d1        ; send Form Feed
  305.  
  306. SER_CLUP:
  307.     bsr    SER_SBOK
  308.     cmp.w    #ERR.NC,d0
  309.     beq.s    SER_CLUP
  310.  
  311. SER_C2:
  312.     MOVE.B    #%11000000,CIAB_PRA ; DTR(7) low (1) not ready to receive
  313.                   ; RTS(6) low (1) nothing to send
  314.  
  315.     lea    SER_TXQ(a0),a2
  316.     move.w    IO.QEOF,a4    ; put EOF marker in queue
  317.     jsr    (a4)
  318.  
  319.     moveq    #ERR.OK,d0    ; signal "no errors"
  320.     RTS
  321.  
  322. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  323. ;  Serial - input / output routine
  324.  
  325. SER_IO:
  326.     pea    SV.PEND(a3)    ; pretend call just before
  327.     move.w    IO.SERIO,a4
  328.     JMP    (A4)
  329.  
  330. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  331. ;  Serial - test for pending input
  332.  
  333. SER_TST:
  334.     lea    SER_RXQ(a0),a2   ; pointer to buffer
  335.     move.w    IO.QTEST,a4
  336.     jmp    (a4)
  337.  
  338. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  339. ;  Serial - Send byte d1
  340.  
  341. SER_SBYT:
  342.     lea    SER_TXQ(a0),a2
  343.  
  344.     move.l    d1,d3
  345.     move.w    IO.QTEST,a4
  346.     jsr    (a4)
  347.     move.l    d3,d1
  348.  
  349.     cmpi.w    #ERR.EF,d0
  350.     beq.s    SER_SB4
  351.  
  352.     moveq    #ERR.OK,d0
  353.  
  354.     cmpi.w    #$6,d2
  355.     bge.s    SER_SB5
  356.  
  357.     moveq    #ERR.NC,d0
  358.  
  359. SER_SB4:
  360.     rts
  361.  
  362. SER_SB5:
  363.     move.b    1+SER_TXD(a0),d3    ; remember old TX code
  364.     move.b    d1,1+SER_TXD(a0)    ; save new TX code
  365.  
  366.     tst.b    1+SER_PROT(a0)
  367.     blt.s    SER_SBOK     ; branch if no eol protocol
  368.  
  369.     cmpi.b    #$0A,d1        ; Line Feed?
  370.     beq.s    SER_SB1
  371.  
  372.     cmpi.b    #$0D,d1        ; Carriage Return?
  373.     bne.s    SER_SBOK     ; branch if neither
  374.  
  375. SER_SB1:
  376.     cmpi.b    #$0A,d3        ; Line Feed?
  377.     beq.s    SER_SB2
  378.  
  379.     cmpi.b    #$0D,d3        ; Carriage Return?
  380.     bne.s    SER_SB3
  381.  
  382. SER_SB2:
  383.     cmp.b    d1,d3
  384.     beq.s    SER_SB3
  385.  
  386.     move.b    #$FF,1+SER_TXD(a0) ; ignore LF in CR/LF couple
  387.     moveq    #ERR.OK,d0
  388.     rts
  389.  
  390. SER_SB3:
  391.     tst.b    1+SER_PROT(a0)
  392.     beq.s    SER_SB6        ; branch if CR/LF protocol
  393.  
  394.     cmp.b    #2,1+SER_PROT(a0)
  395.     beq.s    SER_SB7        ; branch if LF
  396.  
  397.     moveq    #$0D,d1        ; else use CR
  398.     bra.s    SER_SBOK
  399.  
  400. SER_SB6:
  401.     moveq    #$0D,d1
  402.     bsr    SER_SBOK
  403.  
  404. SER_SB7:
  405.     moveq    #$0A,d1
  406.  
  407. SER_SBOK:
  408.     tst.b    SV_TRAN(a6)    ; key translation present ?
  409.     beq.s    L00BDE        ; if not -> L00BDE
  410.  
  411. SER_SBOK1:
  412.     BSR    TRAKEY_S
  413.  
  414.     rts
  415.  
  416. L00BDE:
  417.     move.w    SER_PAR(a0),d0
  418.     MOVE.B    L00BEA(PC,D0.W),D0
  419.     JMP    L00BEA(PC,D0.W)
  420. L00BEA:
  421.     DC.B    WNOPAR-L00BEA
  422.     DC.B    WODD-L00BEA
  423.     DC.B    WEVEN-L00BEA
  424.     DC.B    WBIT7-L00BEA
  425.     DC.B    WBIT8-L00BEA
  426.     DC.B    0
  427.  
  428. ; --------------------------------------------------------------
  429. WBIT7:
  430.     BSET    #7,D1
  431.  
  432. ; --------------------------------------------------------------
  433. WNOPAR:
  434.     lea    SER_TXQ(a0),a2
  435.  
  436.     move.w    IO.QIN,a4    ; put byte d1 into queue a2
  437.     jsr    (a4)
  438.     BRA    L00C74
  439.  
  440. ; --------------------------------------------------------------
  441. WBIT8:
  442.     BCLR    #7,D1
  443.     BRA.S    WNOPAR
  444.  
  445. ; --------------------------------------------------------------
  446. WODD:
  447.     BSR    L00C76
  448.     BCHG    #7,D1
  449.     BRA.S    WNOPAR
  450.  
  451. ; --------------------------------------------------------------
  452. WEVEN:
  453.     BSR    L00C76
  454.     BRA.S    WNOPAR
  455.  
  456. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  457. ;  Serial - fetch byte
  458.  
  459. SER_FBYT:
  460.     move.l    SV_SER1C(a6),a2          ; Pointer to buffer
  461.  
  462.     move.w    IO.QOUT,a4
  463.     jsr    (a4)
  464.  
  465.     BNE    L00C74
  466.  
  467. SER_RDAT:
  468.     MOVE.W    $1A(A0),D3
  469.     MOVE.B    L00C3A(PC,D3.W),D3
  470.     JMP    L00C3A(PC,D3.W)
  471.  
  472. L00C3A:
  473.     DC.B    RNOPAR-L00C3A
  474.     DC.B    RIMPAR-L00C3A
  475.     DC.B    RPAR-L00C3A
  476.     DC.B    RBIT71-L00C3A
  477.     DC.B    RBIT70-L00C3A
  478.     DC.B    0
  479.  
  480. ; --------------------------------------------------------------
  481. RBIT71:
  482.     BCHG    #7,D1
  483.     BRA.S    RBIT70
  484.  
  485. ; --------------------------------------------------------------
  486. RIMPAR:
  487.     BCHG    #7,D1
  488.  
  489. ; --------------------------------------------------------------
  490. RPAR:
  491.     BSR.S    L00C76
  492.  
  493. ; --------------------------------------------------------------
  494. RBIT70:
  495.     BTST    #7,D1
  496.     BEQ.S    RNOPAR
  497.     MOVEQ    #-13,D0        ; XMIT error
  498.  
  499. ; --------------------------------------------------------------
  500. RNOPAR:
  501.     tst.b    SV_TRAN(a6)    ; Key translation present ?
  502.     BEQ.S    L00C66
  503.     BSR    TRAKEY_R
  504.  
  505. L00C66:
  506.     move.b    1+SER_RXD(a0),d3    ; remember old RX code
  507.     move.b    d1,1+SER_RXD(a0)    ; save new RX code
  508.  
  509.     tst.b    1+SER_PROT(a0)
  510.     blt.s    L00C74        ; branch if no EOL protocol
  511.  
  512.     cmpi.b    #$0A,d1        ; Line Feed?
  513.     beq.s    RNOP1
  514.  
  515.     cmpi.b    #$0D,d1        ; Carriage Return?
  516.     bne.s    L00C74        ; branch if neither
  517.  
  518. RNOP1:
  519.     cmpi.b    #$0A,d3        ; Line Feed?
  520.     beq.s    RNOP2
  521.  
  522.     cmpi.b    #$0D,d3        ; Carriage Return?
  523.     bne.s    RNOP3
  524.  
  525. RNOP2:
  526.     cmp.b    d1,d3
  527.     beq.s    RNOP3
  528.  
  529.     move.b    #$FF,1+SER_RXD(a0) ; ignore LF in CR/LF couple
  530.     moveq    #ERR.NC,d0
  531.     rts
  532.  
  533. RNOP3:
  534.     moveq    #$0A,d1        ; change to LF
  535.  
  536. L00C74:
  537.     RTS
  538.  
  539. ; --------------------------------------------------------------
  540. L00C76:
  541.     MOVEQ    #6,D3
  542.     MOVE.B    D1,D4
  543.  
  544. L00C7A:
  545.     ROR.B    #1,D1
  546.     EOR.B    D1,D4
  547.     DBF    D3,L00C7A
  548.     ROXL.B    #1,D4
  549.     ROXR.B    #1,D1
  550.     RTS
  551.  
  552. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  553. ;  Translate key d1 for sending
  554.  
  555. TRAKEY_S:
  556.     MOVEM.L    D1-D3/A1,-(A7)
  557.     MOVEQ    #0,D0
  558.     movea.l    SV_TRTAB(a6),a1    ; Pointer to key translation
  559.     MOVE.W    2(A1),D2
  560.     LEA    0(A1,D2.W),A1
  561.     TST.B    D1
  562.     BEQ.S    L0B5D6
  563.     MOVE.B    0(A1,D1.W),D0
  564.     TST.B    D0
  565.     BEQ.S    L0B58E
  566.     MOVE.B    D0,D1
  567.     BRA.S    L0B5D6
  568.  
  569. L0B58E:
  570.     MOVE.L    D1,D3
  571.  
  572.     move.w    IO.QTEST,a4
  573.     jsr    (a4)
  574.  
  575.     MOVE.L    D3,D1
  576.     CMPI.W    #$FFF6,D0
  577.     BEQ.S    L0B5DC
  578.     MOVEQ    #0,D0
  579.     CMPI.W    #$0003,D2
  580.     BGE.S    L0B5AA
  581.     MOVEQ    #-1,D0
  582.     BRA.S    L0B5DC
  583.  
  584. L0B5AA:
  585.     MOVEA.L    SV_TRTAB(A6),A1    ; pointer to key translation
  586.     MOVE.W    4(A1),D2     ; Start of system messages
  587.     LEA    0(A1,D2.W),A1
  588.     MOVE.B    (A1)+,D3
  589.  
  590. L0B5B8:
  591.     BEQ.S    L0B5DC
  592.     CMP.B    (A1)+,D1
  593.     BEQ.S    L0B5C4
  594.     ADDQ.L    #3,A1
  595.     SUBQ.B    #1,D3
  596.     BRA.S    L0B5B8
  597.  
  598. L0B5C4:
  599.     MOVE.B    (A1)+,D1
  600.     bsr    L00BDE        ; put byte d1 into queue a2
  601.     MOVE.B    (A1)+,D1
  602.     bsr    L00BDE        ; put byte d1 into queue a2
  603.     MOVE.B    (A1),D1
  604.  
  605. L0B5D6:
  606.     bsr    L00BDE        ; put byte d1 into queue a2
  607.  
  608. L0B5DC:
  609.     MOVEM.L    (A7)+,D1-D3/A1
  610.     RTS
  611.  
  612. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  613. ;  translate key d1 for reading
  614.  
  615. TRAKEY_R:
  616.     MOVEM.L    D0/D2/A1,-(A7)    ; D0-D2/A1 as before can not
  617.                 ; work correctly
  618.     MOVEA.L    $146(A6),A1    ; pointer to key translation
  619.     MOVE.W    2(A1),D2
  620.     LEA    0(A1,D2.W),A1
  621.     MOVE.B    0(A1,D1.W),D0
  622.     TST.B    D0
  623.     BEQ.S    L0B60E
  624.     MOVE.W    D1,D2
  625.  
  626. L0B5FC:
  627.     MOVE.B    0(A1,D2.W),D0
  628.     CMP.B    D0,D1
  629.     BEQ.S    L0B60C
  630.     ADDQ.B    #1,D2
  631.     CMP.B    D2,D1
  632.     BNE.S    L0B5FC
  633.     BRA.S    L0B60E
  634.  
  635. L0B60C:
  636.     MOVE.B    D2,D1
  637.  
  638. L0B60E:
  639.     MOVEM.L    (A7)+,D0/D2/A1    ; D0-D2/A1 as before can not
  640.                 ; work correctly
  641.     RTS
  642.  
  643. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  644. ;  poll interrupt server for serial port. If interrupts are off,
  645. ;  restarts interrupts by sending a byte.
  646.  
  647. POLL_SERv:
  648.     bsr    SER_SEND     ; if transmit buffer is
  649.                 ; empty, and CTS bit is
  650.                 ; clear, then send a byte
  651.  
  652.     bsr    SER_RECV     ; if there's room in input
  653.                 ; buffer, fetch byte.
  654. POLL_X:
  655.     rts
  656.  
  657. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  658. ;  external interrupt server for serial port
  659.  
  660. XINT_SERv:
  661.     movem.l    d7/a0,-(a7)
  662.  
  663.     move.w    INTENAR,d7    ; read interrupt enable reg
  664.     btst    #0,d7        ; branch if ints not on
  665.     beq    XINT_1
  666.  
  667.     move.w    INTREQR,d7    ; read interrupt request reg
  668.     btst    #0,d7        ; branch if from output
  669.     bne    TBE_XINT     ; buffer empty
  670.     bra    XINT_OTHer
  671.  
  672. XINT_1:
  673.     btst    #11,d7        ; branch if ints not on
  674.     beq    XINT_OTHer
  675.  
  676.     move.w    INTREQR,d7    ; read interrupt request reg
  677.     btst    #11,d7        ; branch if from input
  678.     bne    RBF_XINT     ; buffer full
  679.  
  680. ; --------------------------------------------------------------
  681. ;  otherwise let another external interrupt server handle it
  682.  
  683. XINT_OTHer:
  684.     movem.l    (a7)+,d7/a0
  685.     rts
  686.  
  687. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  688. ;  RBF Interrupt. Reads a byte into the queue when serial data
  689. ;  is ready (read buffer is full).
  690.  
  691. RBF_XINT:
  692.     bsr    SER_RECV     ; send next byte
  693.  
  694.     move.w    #%0000100000000000,INTREQ ; reset RBF int.
  695.  
  696. RBF_XINT_X:
  697.     bra.s    XINT_EXIt
  698.  
  699. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  700. ;  TBE Interrupt. Tries to send another byte from queue when
  701. ;  transmit buffer becomes empty.
  702.  
  703. TBE_XINT:
  704.     move.w    #%0000000000000001,INTREQ ; reset TBE int.
  705.  
  706.     bsr    SER_SEND     ; send next byte
  707.  
  708. TBE_XINT_X:
  709.  
  710. ; -------------------------------------------------------------
  711. XINT_EXIt:
  712.     bra.s    XINT_OTHer
  713.  
  714. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  715. SER_RECV:
  716.     movem.l    d0-d3/a0-a4,-(a7)
  717.  
  718.     MOVE.L    SV_SER1C(a6),a2    ; Receive queue channel 1
  719.     MOVE.L    A2,D0        ; channel open ?
  720.     BEQ.S    SER_RECVX    ; no, ignore data.
  721.  
  722.     move.b    1+SER_TXHS-SER_RXQ(a2),d1
  723.     ble.s    SER_RECV1    ; branch if no handshake
  724.  
  725.     move.b    CIAB_PRA,d1
  726.     ori.b    #%10000000,d1
  727.     MOVE.B    d1,CIAB_PRA    ; DTR(7) low (1) not ready to receive
  728.  
  729. SER_RECV1:
  730.     btst    #(14-8),SERDATR    ; receive buffer full?
  731.     beq.s    SER_RECV2    ; no, enable transmission
  732.  
  733.     MOVE.W    SERDATR,D1    ; get data
  734.  
  735.     move.w    #%0000100000000000,INTREQ ; reset RBF int.
  736.  
  737.     move.w    IO.QIN,a4
  738.     jsr    (a4)        ; put byte d1 into queue a2
  739.     TST.W    D0        ; any errors ?
  740.     BEQ.S    SER_RECV1    ; no, check if another
  741.  
  742.     bra.s    SER_RECVX    ; yes, stop transmission
  743.  
  744. SER_RECV2:
  745.     move.w    IO.QTEST,a4
  746.     jsr    (a4)        ; check free space in queue
  747.  
  748.     CMP.W    #10,D2        ; receiv queue nearly full?
  749.     BCS.S    SER_RECVX    ; yes, stop reception
  750.  
  751.     move.b    CIAB_PRA,d1
  752.     and.b    #%01111111,d1
  753.     move.b    d1,CIAB_PRA    ; DTR(7) high (0) ready to receive
  754.  
  755. SER_RECVX:
  756.     movem.l    (a7)+,d0-d3/a0-a4
  757.     rts
  758.  
  759. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  760. ;  write next byte from queue to serial port
  761.  
  762. SER_SEND:
  763.     movem.l    d0-d1/d7/a2-a4,-(a7)
  764.  
  765.     move.l    SV_SER1C(a6),d1    ; address of receive Q
  766.     beq.s    SER_S_X        ; exit if Q doesn't exist
  767.  
  768.     move.w    #(SER_TXQ-SER_RXQ),a2
  769.     adda.l    d1,a2        ; address of transmit Q
  770.  
  771.     move.b    1+SER_TXHS-SER_TXQ(a2),d1
  772.     ble.s    SER_S1
  773.  
  774.     btst    #4,CIAB_PRA    ; test CTS bit
  775.     bne.s    SER_S_X        ; exit if not ready
  776.  
  777. SER_S1:
  778.     btst    #(13-8),SERDATR    ; transmit buffer empty?
  779.     BEQ.S    SER_S_X
  780.  
  781.     moveq    #0,d1
  782.     move.w    IO.QOUT,a4
  783.     jsr    (a4)        ; get byte d1 from queue a2
  784.     tst.l    d0
  785.     beq.s    SER_S_DO     ; send it if no error
  786.  
  787.     move.b    CIAB_PRA,d0    ; otherwise...
  788.     ori.b    #%01000000,d0
  789.     move.b    d0,CIAB_PRA    ; RTS(6) low (1) nothing to send
  790.  
  791.     bra.s    SER_S_X        ; and exit
  792.  
  793. SER_S_DO:
  794.     move.b    CIAB_PRA,d0
  795.     andi.b    #%10111111,d0
  796.     move.b    d0,CIAB_PRA    ; RTS(6) high (0) ready to send
  797.  
  798.     or.w    #$300,d1     ; set two stop bits
  799.     move.w    #%0000000000000001,INTREQ ; reset TBE int.
  800.     move.w    D1,SERDAT    ; write data to serial port
  801.  
  802. SER_S_X:
  803.     movem.l    (a7)+,d0-d1/d7/a2-a4
  804.     RTS
  805.  
  806. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  807. ;  Custom LVL7 routine to initialise hardware
  808.  
  809. MY_LVL7:
  810.     bsr    INIT_HW
  811.  
  812.     subq.l    #4,a7
  813.     movem.l    a3,-(a7)
  814.     move.l    AV.SERV,a3
  815.     move.l    SV.LVL7link(a3),a3
  816.     move.l    4(a3),4(a7)    ; address of next routine
  817.     movem.l    (a7)+,a3
  818.  
  819.     rts
  820.  
  821. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  822. ;  A patch to replace TRAP#1 calls to: MT_BAUD (d0=$12)
  823.  
  824. MY_TRP1:
  825.     bsr    INI_A5A6
  826.  
  827.     cmp.b    #$12,d0
  828.     beq    MT_BAUD
  829.  
  830.     movem.l    (a7)+,d7/a5/a6    ; restore registers
  831.  
  832.     subq.l    #4,a7
  833.     movem.l    a3,-(a7)
  834.     move.l    AV.SERV,a3
  835.     move.l    SV.TRP1link(a3),a3
  836.     move.l    4(a3),4(a7)    ; address of next routine
  837.     movem.l    (a7)+,a3
  838.  
  839.     rts
  840.  
  841. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  842. ; initialise A5 and A6 prior to performing a TRAP routine
  843.  
  844. INI_A5A6
  845.     SUBQ.L    #8,A7
  846.     MOVE.L    8(A7),-(A7)
  847.     MOVEM.L    D7/A5/A6,4(A7)
  848.  
  849.     move.l    a7,d7
  850.     andi.l    #$FFFF8000,d7
  851.     move.l    d7,a6        ; Calc address of sys vars
  852.  
  853.     LEA    4(A7),A5     ; A5 points to saved
  854.                 ; Registers D7,A5,A6
  855.     MOVEQ    #$7F,D7
  856.     AND.L    D7,D0
  857.     RTS
  858.  
  859. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  860. ;  TRAP #1 with D0=$12
  861. ;  set baud rate
  862.  
  863. MT_BAUD:
  864.     MOVEM.L    D2/D6/A0-A2,-(A7)
  865.     MOVE.L    D1,D0        ; D0=baudrate
  866.     MOVE.L    #3579546,D1    ; D1=1/2.79365E-7
  867.  
  868.     btst    #0,d0
  869.     bne.s    MT_BAUD1
  870.  
  871.     lsr.l    #1,d0
  872.     lsr.l    #1,d1
  873.  
  874. MT_BAUD1:
  875.     DIVU    D0,D1        ; D1=D1/baudrate
  876.     AND.L    #$FFFF,D1    ; mask out remainder
  877.     SUBQ.W    #1,D1        ; to be exact
  878. ;    ORI.W   #$8000           ; we may receive two stop bits
  879.     move.w    d1,SERPER    ; write to SERPER
  880.     MOVEM.L    (A7)+,D2/D6/A0-A2
  881.  
  882.     moveq    #0,d0
  883.  
  884. ; --------------------------------------------------------------
  885. ;  exit from TRAP call
  886.  
  887. TRAP1_X    movem.l    (a7)+,d7/a5/a6    ; exit from exception
  888.     rte
  889.  
  890. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  891.     END
  892.